import socket
from typing import Optional

from ..models import UserContainerLink, ContainerInfoDict
from ..baseapp import db


def get_free_port(min_port: int, max_port: int) -> Optional[int]:
    """
    Finds an available port within the specified range [min_port, max_port].

    :param min_port: The minimum port number in the range.
    :param max_port: The maximum port number in the range.
    :return: An available port number or None if no port is available.
    """
    for port in range(min_port, max_port + 1):
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            try:
                s.bind(("", port))
                return port
            except OSError:
                continue
    return None


def get_container_user_id(container_id: str) -> Optional[int]:
    """
    Get the user ID associated with a container.
    If the container is not linked to any user, it will return None.

    :param container_id: The ID of the container.
    :return: The user ID associated with the container.
    """
    container_info = UserContainerLink.query.filter_by(
        container_id=container_id
    ).first()
    if container_info is None:
        return None
    return container_info.user_id


def link_container_and_user(
    container_id: str, user_id: int, dev_env_id: int, port: int, host_machine_id: int
):
    """
    Create a new UserContainerLink object and add it to the database.
    Linking the container to the user in the database.
    """
    container_info = UserContainerLink(
        container_id=container_id,
        user_id=user_id,
        dev_env_id=dev_env_id,
        port=port,
        host_machine_id=host_machine_id,
    )
    db.session.add(container_info)
    db.session.commit()
